﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading;
using GameObjects;
using WebReferenceManager.ServiceReference1;

namespace WebReferenceManager
{
    public class ServerConnection
    {
        public Service1Client WebService;
        private int? serverGameTurn;
        private Thread gameTurnThread;
        public List<UnitOrderDto> DtoOrders;
        private DateTime LastGetOrdersRequest;
        private bool deleteResponse;
        private bool sendResponse;
        //public bool NewOrdersReady;

        public ServerConnection()
        {
            WebService = new Service1Client();
        }

        public ServerConnection(string configurationName, string remoteAddress)
        {
            WebService = new Service1Client(configurationName, remoteAddress);
        }

        public string Address
        {
            get { return WebService.Endpoint.Address.ToString(); }
        }

        public void SendOrder(int gameId, int turn, int factionId, UnitMoveOrder order)
        {
            SendOrders(gameId, turn, factionId, new List<UnitMoveOrder> { order }); 
        }

        public void SendOrders(int gameId, int turn, int factionId, List<UnitMoveOrder> orders)
        {
            var dtoOrders = new List<UnitOrderDto>();
            foreach (var o in orders)
            {
                var hexes = new List<int>();
                foreach (var h in o.Hexes)
                    hexes.Add(h.Id);

                dtoOrders.Add(new UnitOrderDto { UnitId = o.Unit.Id, Hexes = hexes.ToArray() });
            }

            var newthread = new Thread(() => SendOrderThread(gameId, turn, factionId, dtoOrders));
            newthread.Start();
        }

        public void GetOrders(int gameId, int turn)
        {
            if (DateTime.Now - LastGetOrdersRequest < new TimeSpan(0, 0, 10))
                return;

            LastGetOrdersRequest = DateTime.Now;
            //NewOrdersReady = false;

            var newThread = new Thread(() => GetOrdersThread(gameId, turn));
            newThread.Start();
        }

        public void DeleteOrder(int gameId, int turn, int unitId)
        {
            var newthread = new Thread(() => DeleteOrderThread(gameId, turn, unitId));
            newthread.Start();
        }

        private void DeleteOrderThread(int gameId, int turn, int unitId)
        {
            deleteResponse = false;
            deleteResponse = WebService.DeleteOrder(gameId, turn, unitId);
            while (!deleteResponse)
            {
                Thread.Sleep(1000);
            }
            //DtoOrders = WebService.GetOrders(gameId, turn).ToList();
            DtoOrders = null;
            LastGetOrdersRequest = DateTime.MinValue;
        }

        private void GetOrdersThread(int gameId, int turn)
        {
            DtoOrders = WebService.GetOrders(gameId, turn).ToList();
            //NewOrdersReady = true;
            LastGetOrdersRequest = DateTime.Now;
        }

        private void SendOrderThread(int gameId, int turn, int factionId, List<UnitOrderDto> dtoOrders)
        {
            sendResponse = false;
            sendResponse = WebService.ReceiveOrders(gameId, turn, factionId, dtoOrders.ToArray());
            while (!sendResponse)
            {
                Thread.Sleep(1000); 
            }
            DtoOrders = null;
            LastGetOrdersRequest = DateTime.MinValue;
        }

        public bool NextTurn(int gameId, int turn)
        {
            if (serverGameTurn != null)
            {
                if (serverGameTurn == turn)
                {
                    //if (gameTurnThread != null)
                    //    gameTurnThread.Abort();
                    //gameTurnThread = null;
                    return true;
                }
                if (serverGameTurn - turn > 1)
                    throw new Exception("Out of sync with server");
                
                serverGameTurn = null;
            }
            if (gameTurnThread == null || !gameTurnThread.IsAlive)
            {
                gameTurnThread = new Thread(() => GetCurrentGameTurn(gameId));
                gameTurnThread.Start();
            }

            return false;
        }

        void GetCurrentGameTurn(int gameId)
        {            
            serverGameTurn = WebService.GetCurrentGameTurn(gameId);
            DtoOrders = null;
            LastGetOrdersRequest = DateTime.MinValue;
            Thread.Sleep(5000);
        }
    }
}
